package com.derbysoft.ota.application.service.impl;

import java.util.Map.Entry;

import com.derbysoft.modules.eip.translator.Translator;
import com.derbysoft.modules.validation.ValidateUtils;
import com.derbysoft.ota.application.service.HotelSearchService;
import com.derbysoft.ota.application.translator.CodeTables;
import com.derbysoft.ota.interfaces.protocol._2009a.OTAHotelSearchRQ;
import com.derbysoft.ota.interfaces.protocol._2009a.OTAHotelSearchRS;
import com.derbysoft.ota.interfaces.protocol._2009a.POSType;
import com.derbysoft.ota.interfaces.protocol._2009a.PropertiesType;
import com.derbysoft.ota.interfaces.protocol._2009a.WarningType;
import com.derbysoft.ota.interfaces.protocol._2009a.WarningsType;
import com.derbysoft.remote.dswitch.core.GenericRQ;
import com.derbysoft.remote.dswitch.core.GenericRS;
import com.derbysoft.remote.dswitch.core.RequestHeader;
import com.derbysoft.remote.dswitch.hotel.dswitch.DSwitch4HotelBuyerWebServiceFactory;
import com.derbysoft.remote.dswitch.hotel.dto.HotelSearchRQ;
import com.derbysoft.remote.dswitch.hotel.dto.HotelSearchRS;
import com.google.common.collect.Maps;
import com.google.inject.Inject;

public class HotelSearchServiceImpl extends AbstractService implements HotelSearchService {

    private Translator<OTAHotelSearchRQ, HotelSearchRQ> rqTranslator;
    private Translator<Entry<OTAHotelSearchRQ, HotelSearchRS>, PropertiesType> rsTranslator;

	@Inject
    public HotelSearchServiceImpl(
        DSwitch4HotelBuyerWebServiceFactory dswitch4HotelBuyerWebServiceFactory,
        Translator<POSType, RequestHeader> requestHeaderTranslator,
        Translator<OTAHotelSearchRQ, HotelSearchRQ> rqTranslator,
        Translator<Entry<OTAHotelSearchRQ, HotelSearchRS>, PropertiesType> rsTranslator) {

    	super(dswitch4HotelBuyerWebServiceFactory, requestHeaderTranslator);
        this.rqTranslator = rqTranslator;
        this.rsTranslator = rsTranslator;
    }

    @Override
    public OTAHotelSearchRS search(OTAHotelSearchRQ otaHotelSearchRQ) {
        GenericRQ<HotelSearchRQ> genericRQ = switchRequest(otaHotelSearchRQ);
        
        ValidateUtils.validate(genericRQ);
		GenericRS<HotelSearchRS> genericRS = dswitch().searchHotels(genericRQ);
		ValidateUtils.validate(genericRS);
		
		return otaResponse(otaHotelSearchRQ, genericRS);
    }

	private GenericRQ<HotelSearchRQ> switchRequest(OTAHotelSearchRQ otaHotelSearchRQ) {
		return new GenericRQ<HotelSearchRQ>(
	        	requestHeader(otaHotelSearchRQ.getPOS()),
	        	rqTranslator.translate(otaHotelSearchRQ)
        );
	}
    
	private OTAHotelSearchRS otaResponse(OTAHotelSearchRQ otaHotelSearchRQ, GenericRS<HotelSearchRS> genericRS) {
	    OTAHotelSearchRS otaHotelSearchRS = new OTAHotelSearchRS();
	    if (!handleResponseHeaders(genericRS, otaHotelSearchRQ, otaHotelSearchRS)) {
	    		otaHotelSearchRS.setProperties(rsTranslator.translate(Maps.immutableEntry(otaHotelSearchRQ, genericRS.getPayload()))
	    	);
	    	
	    	if (otaHotelSearchRS.getProperties() == null || otaHotelSearchRS.getProperties().getProperty().isEmpty()) {
	    		if (otaHotelSearchRS.getWarnings() == null) {
	    			otaHotelSearchRS.setWarnings(new WarningsType());
	    			WarningType warning = new WarningType();
	    			warning.setType(CodeTables.EWT_BIZ_RULE);
	    			warning.setShortText("No Properties Were Found That Matched The Search Criteria");
				otaHotelSearchRS.getWarnings().getWarning().add(warning);
	    		}
	    	}
	    }
        otaHotelSearchRS.setCriteria(otaHotelSearchRQ.getCriteria());
		return otaHotelSearchRS;
	}
	
}
